﻿#include "MainGame.h"
#include "ShareComponents.h"
#include "RSManager.h"
#include "QuadTree.h"
#include "Box.h"
#include "FWGame.h"
#include "FWKeyboard.h"
#include "FWGraphic.h"
#include "FWContentManager.h"
#include "Map.h"
#include "Camera.h"

#include "Object.h"
#include "IS.h"
#include "FWTexture.h"
#include <list>
#include "StaticObject.h"
#include "Player.h"
#include "Bridge.h"
#include "BulletManager.h"
#include "Bullet.h"

#include "DefenseCannon.h"
#include "Fire.h"
#include "Sniper.h"
#include "StandSniper.h"
#include "Cannon.h"
#include "Rock.h"
#include "WallTurret.h"
#include "SweptAABB.h"
#include "BackGround.h"
#include "EnemyDie.h"
#include "Barracks.h"


MainGame::MainGame(HINSTANCE hIns,char* windowName,int w,int h):FWGame(hIns,windowName,w,h)
{
	D3DXMatrixIdentity(&this->matrix_transform);
}

MainGame::~MainGame(void)
{
}

void MainGame::load()
{	
	_initGameComponents();
	_loadEnemy();
	br = new Barracks(new Box(D3DXVECTOR2(200,300),D3DXVECTOR2(32,32),D3DXVECTOR2()));
	br->init();
	Box* player_pos = new Box(D3DXVECTOR2(6000, 400), D3DXVECTOR2(0, 0), D3DXVECTOR2(0, 0));		
	_player = new Player(player_pos);	
	_player->init();
	gl_map =  _map;
	this->_bridge = _map->getStaticBridge();
	for (Bridge* i : _bridge)
	{
		_quadTree->insert(i);
	}
	BulletManager::create();
	e = new EnemyDie(player_pos);
	e->init();

	worldObject.push_back(br);
	//128	1632	256	16
	fire = new Fire(new Box(D3DXVECTOR2(128,1632 + 16),D3DXVECTOR2(256,16),D3DXVECTOR2(0,0)));
	//64	544
	rock = new Rock(new Box(D3DXVECTOR2(64,544),D3DXVECTOR2(64,64),D3DXVECTOR2(0,0)));
	rock->init();
	fire->init();
	gl_MainGame =  this;
}

void MainGame::render()
{	
	graphic->clear(D3DCOLOR_XRGB(255,255,255));
	graphic->begin(_cam->getTransformedMatrix());	
	this->_map->render();	
	_bg->render();
	//RenderDebug();
	for (Box* i : check)
	{
		graphic->tDraw(test,i->getRect(),i->getCenter(),D3DCOLOR_XRGB(255,255,255));
	}
	_renderEnemies();
	_player->render();
	for (Bridge* i : _bridge)
	{
		i->render();
	}
	fire->render();
	rock->render();
	e->render();
  	for (Box* i : _collision)
  	{
  		graphic->tDraw(test,i->getRect(),i->getCenter(),D3DCOLOR_XRGB(0,0,0));
  	}
	graphic->end();
}

void MainGame::shutdown()
{

}

void MainGame::update(float time)
{		
	active.clear();
	check.clear();
	_collision.clear();
	keyboard->getState();	
	e->update();
#pragma region EFFECT
	_bg->update();
#pragma endregion

#pragma region Insert game object to quadtree
	_quadTree->clear();
	_player->update();
	_cam->update(_player->getBox()->_position);

	for (Bridge* i : _bridge)
	{
		i->update();
	}	
	list<Bullet*> bullets =  BulletManager::getInstance()->getUsingList();
	for (Bullet* b : bullets)
	{
		if(!SweptAABB::checkAABB(b->getBox(),_cam->getBox()))
		{
			BulletManager::getInstance()->collect(b);
			continue;
		}		
		b->update();
		_quadTree->insert(b);
	}
	list<Object*> died;
	for (Object* i : worldObject)
	{
		if(!i->isAlive())
		{
			died.push_back(i);
			continue;
		}
		i->update();
		_quadTree->insert(i);
	}
	for (Object* i: died)
	{
		worldObject.remove(i);
	}
	
	active = _quadTree->queryObject(_cam->getBox());

	float _remainTime;
	float nx, ny;
	Box* b1;
	Box* b2;
#pragma endregion Insert game object to quadtree

#pragma region World
	for (Object*i : active)
	{
		if(i->getObjectType() == ObjBulletEnemy||i->getObjectType() == ObjBulletPlayer || i->getObjectType() == ObjBarracks) continue;		
		//không update đạn						
		list<Object*> collision = _quadTree->queryObject(i->getBoundBox());

		check.push_back(i->getBoundBox());

		for (Object* j : collision)
		{
			if(j == i) continue;
			if(j->getObjectType() == ObjBulletPlayer)
			{							
				switch (i->getObjectType())
				{
				case ObjEnemy_DYNAMID:
					{
						 b1 = i->getCollisionBox();
						 b2 = j->getCollisionBox();
						 _collision.push_back(b1);
						 _collision.push_back(b2);
						b1->_v -= b2->_v;
						_remainTime = SweptAABB::sweptAABBCheck(b1,b2,nx,ny);
						if(_remainTime < 1.0f) 
						{													
							EnemyDie* x = new EnemyDie(b1);
							x->init();
							worldObject.push_back(x);
							//i->collide(2);
							i->collide(((Bullet*)j)->getDamage());
							BulletManager::getInstance()->collect((Bullet*)j);	
						}
					}
					break;
				case ObjEnemy_STATIC:
					{
						 b1 = j->getCollisionBox();
						 b2 = i->getCollisionBox();
						 _collision.push_back(b1);
						 _collision.push_back(b2);
						_remainTime = SweptAABB::sweptAABBCheck(b1,b2,nx,ny);
						if(_remainTime < 1.0f) 
						{																					
							i->collide(((Bullet*)j)->getDamage());
							BulletManager::getInstance()->collect((Bullet*)j);
						}
					}
					break;
				}
			}
		}
	}
#pragma endregion World

#pragma region Player
	check.push_back(_player->getBoundBox());
	list<Object*> lcollision = _quadTree->queryObject(_player->getBoundBox());	
	for (Object* i : lcollision)
	{
		switch (i->getObjectType())
		{
		case ObjEnemy_DYNAMID:
			{
				Box* b1 = i->getCollisionBox();
				Box* b2 = _player->getCollisionBox();				
				b1->_v -= b2->_v;
				float time = SweptAABB::sweptAABBCheck(b1,b2,nx,ny);
				if(time < 1.0f) 
				{
					EnemyDie* x = new EnemyDie(b1);
					x->init();
					worldObject.push_back(x);
					_player->collide();
					//:D
					_collision.push_back(b1);
					_collision.push_back(b2);
				}
			}
			break;
		case ObjEnemy_STATIC:
			{
				b2 = i->getCollisionBox();
				b1 = _player->getCollisionBox();
				_collision.push_back(b1);
				_collision.push_back(b2);	
				_remainTime = SweptAABB::sweptAABBCheck(b1,b2,nx,ny);
				if(_remainTime < 1.0f) 
				{
					EnemyDie* x = new EnemyDie(b1);
					x->init();
					worldObject.push_back(x);
					_player->collide();
					//player die here
					//:D
				}
			}
			break;
		case ObjBulletEnemy:
			{
				b1 = i->getCollisionBox();
				b2 = _player->getCollisionBox();
				_collision.push_back(b1);
				_collision.push_back(b2);
				b1->_v -= b2->_v;
				_remainTime = SweptAABB::sweptAABBCheck(b1,b2,nx,ny);
				if(_remainTime < 1.0f) 
				{
					//player die here
					//:D				
					EnemyDie* x = new EnemyDie(b1);
					x->init();
					worldObject.push_back(x);
					_player->collide(((Bullet*)i)->getDamage());
					BulletManager::getInstance()->collect((Bullet*)i);
				}
			}
			break;
		}
	}
#pragma endregion Player



	keyboard->saveState();
}

void MainGame::RenderDebug()
{
	for(StaticObject* i : grounds)
	{
		graphic->tDraw(test,i->getBox()->getRect(),i->getBox()->getCenter(),D3DCOLOR_XRGB(5,25,55));
	}
	//graphic->tDraw(test,gl_ground_player->getRect(),gl_ground_player->getCenter(),D3DCOLOR_XRGB(5,255,55));

	if (gl_predict)
	{
		graphic->tDraw(test,gl_predict->getRect(),gl_predict->getCenter(),D3DCOLOR_XRGB(0,0,255));
	}

	//graphic->tDraw(test,gl_player->getRect(),gl_player->getCenter(),D3DCOLOR_XRGB(255,255,255));
	if(gl_ground != NULL)
		graphic->tDraw(test,gl_ground->getRect(),gl_ground->getCenter(),D3DCOLOR_XRGB(255,0,0));
	graphic->tDraw(test,gl_move->getRect(),gl_move->getCenter(),D3DCOLOR_XRGB(0,0,0));
	//if(gl_fall!= NULL)
	//graphic->tDraw(test,gl_fall->getRect(),gl_fall->getCenter(),D3DCOLOR_XRGB(100,100,100));
	

}

void MainGame::_loadEnemy()
{
	//player load cho nao vay
	Box* is_pos = new Box(D3DXVECTOR2(90, 300), D3DXVECTOR2(0, 0), D3DXVECTOR2(2.4f, 0));
	is = new IS(is_pos);
	is->init();
	worldObject.push_back(is);


	worldObject = _map->getObject();	
	worldObject.push_back(is);
}

void MainGame::_renderEnemies()
{
	
	list<Object*> renderList = _quadTree->queryObject(_cam->getBox());
	for (Object* i : renderList)
	{
		i->render();
	}
}

void MainGame::_initGameComponents()
{
	this->keyboard = new FWKeyboard(this);	
	if(!keyboard->init()) MessageBox(NULL,"Error keyboard!","Error!",MB_OK);		
	gl_keyboard = this->keyboard;
	this->graphic = new FWGraphic(this);		
	graphic->init();	
	gl_graphic = graphic;	
	content  = new FWContentManager(this);
	gl_content = content;	
	RSManager::getInstance()->Init();
	this->_map = new Map(MAP1);	
	this->_map->readMap("Resources\\MAP\\map1.txt");
	_bg = new BackGround(1);
	_quadTree = new QuadTree(new Box(D3DXVECTOR2(0,0),D3DXVECTOR2(_map->getWidth() * 32, _map->getHeight() * 32),D3DXVECTOR2(0, 0)));
	_cam = new Camera(0, _map->getWidth() * 32, _map->getHeight() * 32);
	gl_camera = _cam;
	test = gl_content->loadTexture("gr.png");
	grounds = _map->getStaticObjects();
	globe_grounds = grounds;
	for (StaticObject* i : grounds)
	{
		_quadTree->insert(i);
	}
	gl_Quadtree = _quadTree;
}

void MainGame::addWorldObject(Object* obj)
{
	worldObject.push_back(obj);
}
